#ifndef USER_PRG_H_
#define USER_PRG_H_

#include "config.h" 
//#include "modbus_reg.h"
//#include "manage_io.h"

#define	NUM_LOGIC			24u		/* 逻辑块数量 */
#define	CH_NUM_DI			10u		/* 大于32需修改滤波和处理代码 */
#define CH_NUM_DO     6u
#define	CH_NUM_DI_GROUP		1u		/* 16 signal as a group */
#define	CH_NUM_LOGIC_IN		3u
#define	CH_NUM_DI_RST		2u
#define	CH_NUM_RELAY		2u
#define	CH_NUM_LOGIC_OUT	2u
#define	CH_NUM_LOGIC_RST	2u
#define	CH_NUM_TWO_HAND		1u

#define	DI_FILT_MAX	10000u	/* 1s, unit is 0.1ms */
#define	DO_DLY_MAX	990100u	/* (99u * 100 * 100) */

#define	DI_FILT_DFT	100u	/* 10ms, unit is 0.1ms */

#define	TWO_HAND_LAG_TIME	4500u	/* 450ms, unit is 0.1ms */
#define	PRG_PO_DLY_TIME		10000u	/* 1000ms, unit is 0.1ms */

#define	RELAY_ADJ_TIME		100u	/* 10ms, unit is 0.1ms */
#define	RELAY_MAX_NUM		4u

#define LED_OFF   0x00u
#define LED_ON    0x01u
#define LED_FLASH 0x02u

typedef struct _factory_config
{
   uint16_t u16_password; //密码管理
   //uint16_t u16_sn1;       //设备编码，备用  18
	 //uint16_t u16_sn2;
	 uint8_t  u8_type;       //设备型号，默认为6：对应8903
   uint8_t  u8_config_id;  //仪表组态信息的编号和8.0代码对应
   // uint8_t  u8_software_ver;//软件版本
   // uint8_t  u8_year;       //年月日
   //uint8_t  u8_month;     
   // uint8_t  u8_day;
	 uint8_t u8_modbus_add;   //设备Modbus地址
	 uint8_t u8_pulse_detection_gap; //输入脉冲检测时间
	 uint8_t u8_res[6];       //工厂组态保留
}factory_config_t;

/****输入传感器数据****/
typedef struct _seneor_dat{
	 uint8_t		u8_sensor_type;    //通道输入的类型
	 uint8_t    u8_sensor_add;     //通道输入是否直接对应输出
	 uint16_t	  u16_input_x;
	 uint16_t	  u16_input_y;
}seneor_dat_t;

/**********输出块位置**********/
typedef  struct  _output_add{
	uint16_t u16_output_x;
	uint16_t u16_output_y;	
}output_add_t;


typedef struct _layer_contorl
{
	uint8_t   u8_function_type;                    //逻辑块类型
	uint8_t   u8_function_in1_add;                 //逻辑快输入通道1地址
	uint8_t   u8_function_in2_add;                 //逻辑快输入通道2地址
	uint8_t   u8_function_in3_add;                 //逻辑快输入通道3地址，备用
	uint8_t   u8_function_in4_add;                 //逻辑快输入通道4地址，备用
  uint8_t   u8_function_out_add;                 //逻辑快输出对应地址，
	uint16_t  u16_time_pra;                        //逻辑块控制时间
	uint16_t  u16_axis_x;                          //功能块的图形地址x坐标
	uint16_t  u16_axis_y;                          //功能块的图形地址y坐标
}layer_contorl_t;


typedef struct _config_pra{
	/*组态数据*/
	factory_config_t  factory_config_pra;       //工厂组态数据
//	uint8_t			    u8_sensor_type[10];       //定义10个通道输入的类型
//	uint8_t         u8_sensor_add[10];        //定义10个通道输入是否直接对应输出
	seneor_dat_t      input_sensor_control[10]; //定义10个通道的传感器输入
	layer_contorl_t logic_control[NUM_LOGIC];   //定义逻辑块得数量
	output_add_t		  out_add[4];               //定义4个输出逻辑块信息
	
	uint16_t        u16_config_crc;             //定义组态数据的CRC校验位,由PC传入RAM
	uint8_t         u8_software_ver;            //软件版本,只读
	uint8_t         u8_res[1];                  //定义1个保留
}config_pra_t;

typedef struct _config_project_name{
		uint16_t        u16_project_name[10];       //组态工程名
}config_project_name_t;

typedef struct _instr_hmi
{
	uint16_t  u16_di;  //DI采样信息
  uint16_t  u16_do;  //DO输出信息
	uint32_t  u32_st_dev_sta; //仪表输入输出故障（短路，不同步）
	uint8_t   u8_mcu_addr; //MCU地址
	uint8_t   u8_dev_fault; //模块故障（SPI通讯,双口RAM比较）
	uint8_t  u8_led_sta[6]; //led输出信息
//	uint16_t  u16_led_sta[6];  //led输出信息 -led输出未处理防止报错暂未用
  uint16_t  u16_run_temper;//运行温度
	uint16_t  u16_pwr_in;    //电源电压
	uint16_t  u16_pwr_coil; //线圈电压
	uint16_t  u16_adc_vref; //ADC参考
//	uint8_t   u8_res[2];
	
}instr_hmi_t;

typedef struct _run_disp_data
{   
	/*运行显示数据*/
	bool_t          layer_control_value[NUM_LOGIC]; //逻辑快的输出值
	instr_hmi_t     instrument_hmi;     //仪表可视化的数据
	uint16_t        u16_vrefint_cal;         //MCU 基准校准
	uint16_t        u16_ts_cal1;             //MCU 温度校准
	uint16_t        u16_config_crc;           //MCU计算出的CRC
	uint8_t         u8_res[2];
}run_disp_data_t;


typedef struct _run_SPI_data
{   
	/*SPI传输数据*/
	uint32_t   u32_st_dev_sta; //仪表输入输出故障（短路，不同步）
	uint16_t   u16_di;  //DI采样信息
  uint16_t   u16_do;  //DO输出信息
	uint8_t    u8_mcu_addr; //MCU地址
	uint8_t    u8_dev_fault; //模块故障（SPI通讯,双口RAM比较）
	uint8_t   u8_led_sta[6]; //led输出信息
//	uint16_t   u16_led_sta[6];
  uint16_t   u16_run_temper;//运行温度
	uint16_t   u16_pwr_in;    //电源电压
	uint16_t   u16_pwr_coil; //线圈电压
	uint16_t   u16_adc_vref; //ADC参考	
	uint16_t   u16_vrefint_cal;         //MCU 基准校准
	uint16_t   u16_ts_cal1;             //MCU 温度校准
}run_SPI_data_t;       //zhou


typedef struct _di_filt_dat{
	uint16_t	u16_filt_pram;
	uint16_t	u16_filt_cnt;
	uint16_t	u16_tim_old;
	bool_t		b8_thld_sta;
	bool_t		b8_vld_sta;
} di_filt_dat_t;

typedef struct _layer_output_res
{
	//  uint8_t   res[2];      //保留2个，用于地址对应
//		bool_t  b8_now_data;
//	  bool_t  b8_old_data;
	
    uint32_t  u32_cnt;     //当前累计计数值
    uint16_t  u16_tim_old; //上次时间刻度
	   bool_t  b8_res[2];    //保留2个,用于其它
}layer_output_res_t;//主要考虑，延时


typedef struct _dev_input_res
	{   bool_t b8_thld_sta;    //上一次值
	  bool_t  b8_vld_sta;      //当前值
    uint16_t  u16_cnt;       //当前累计计数值
    uint16_t  u16_tim_old;   //上次时间刻度
}dev_input_res_t;//主要考虑

typedef struct _relay_sta_dat{
	uint16_t	u16_flip_cnt;
	uint16_t	u16_adj_rslt;
	tim_dat_t	st_tim;
	bool_t		b8_out_old;
	uint8_t   res;
} relay_sta_dat_t;

typedef struct _run_aux_data
{   
	/*运行辅助数据*/
	uint16_t        u16_di_val;      //di采样值
  uint16_t        u16_do_val;      //do输出值
	uint16_t        u16_do_pul;      //驱动脉冲输出
	uint16_t        u16_mcua_di;     //MCUA采集到的有效值
	uint16_t        u16_mcub_di;     //MCUB采集到的有效值
	uint16_t			  u16_mcua_do;     //muca要输出的DO
	uint16_t			  u16_mcub_do;     //mucb要输出的DO

	di_filt_dat_t	       sta_di_filt[CH_NUM_DI]; //输入滤波处理
	tim_dat_t            sta_di_vote[CH_NUM_DI];  //输入不平衡处理
  diag_di_info_t	     st_diag_di_info[MAX_IO_NUM_DI];//输入故障处理
	diag_do_sta_t	       st_do_diag_sta;  //输出DO诊断控制
	diag_do_info_t	     st_diag_do_info[MAX_IO_NUM_DO];//输出故障处理
  dev_input_res_t      sta_di_control[CH_NUM_DI];//
	layer_output_res_t   delay_control[NUM_LOGIC]; //定义延时时间
	
	//uint8_t   res[2];      //保留2个，用于地址对应
	uint16_t u16_sys_cnt;       //定义系统时间 主要考虑双手
	uint16_t u16_sys_tim_old;
	uint32_t u32_st_dev_sta;  //从SPI传来的输入输出诊断数据
  bool_t   b8_led_flashflag[6]; //LED灯闪烁标志，代表曾经闪烁过
	relay_sta_dat_t	sta_relay;
	
//	led_sta_dat_t     sta_led[6];  //led输出处理
  uint16_t     TimeStepNum;
	
}run_aux_data_t;



//typedef struct _prg_dat{
//	inst_prg_in_t		st_prg_in;
//	inst_prg_out_t		st_prg_out;
//	inst_prg_logic_t	st_prg_logic;
//	inst_prg_rst_t		st_prg_rst;
//}prg_dat_t;

//typedef struct _mb_app_iec_dat{
//	inst_parm_t			st_parm;
//	prg_dat_t			st_prg_2a;
//	prg_dat_t			st_prg_4s;
//	uint16_t			u16_crc;
//	uint16_t			u16_password;
//	uint16_t			u16_flash_wd_idx;
//}mb_app_iec_dat_t;

//typedef struct _mb_app_hmi_dat{
//	monitor_dev_sta_t		st_dev_sta;
//	monitor_diag_rslt_t		st_diag_rslt;
//	monitor_di_sta_t		st_di_sta;
//	monitor_do_sta_t		st_do_sta;
//}mb_app_hmi_dat_t;

//typedef struct _flash_dat{
//	mb_app_iec_dat_t	st_iec;
//	uint16_t			u16_crc;
//}flash_t;

//typedef struct _ch_fault_dat{
//	bool_t		b8_vote;
//	bool_t		b8_ex;
//}ch_fault_dat_t;

//typedef struct _di_fault_dat{
//	bool_t		b8_on;
//	bool_t		b8_off;
//	bool_t		b8_ex;
//	bool_t		b8_pt;
//}di_fault_dat_t;

//typedef struct _vote_di_dat{
//	tim_dat_t		st_ex_tim;
//	di_fault_dat_t	st_fault;
//}vote_di_dat_t;

//typedef struct _di_sta_dat{
//	uint16_t		u16_di_type;
//	bool_t			b8_edge_rise;
//	bool_t			b8_edge_falling;
//	bool_t			b8_curt_val;
//	uint8_t			u8_fault;
//	vote_di_dat_t	st_vote;
//} di_sta_dat_t;

//typedef struct _do_sta_dat{
//	uint32_t	u32_dly_on;
//	uint32_t	u32_dly_off;
//	uint32_t	u32_dly_cnt;
//	uint16_t	u16_tim_old;
//	bool_t		b8_cnt_flg_on;
//	bool_t		b8_old_sta;
//} do_sta_dat_t;



typedef struct _rst_sta_dat{
	uint16_t	u16_rst_type;
	uint8_t		u8_in_vld_cnt;
	bool_t		b8_vld_sta;
} rst_sta_dat_t;



typedef struct _two_hand_sta_dat{
	uint16_t	u16_lag_parm;
	uint16_t	u16_lag_cnt;
	uint16_t	u16_tim_old;
	uint8_t		u8_in_vld_cnt;
	bool_t		b8_cnt_flg;
	bool_t		b8_act;
	bool_t		b8_vld_sta;
} two_hand_sta_dat_t;

#define	IN_VLD_THLD		200u	/* larger than 10ms */

typedef struct _exch_safe_dat{
	uint16_t	u16_di;
	uint16_t	u16_do;
}exch_safe_dat_t;



#define	VOTE_ERR_FILT		50u		/* 5ms, unit is 0.1ms */
#define	CH_EX_ASYNC_FILT	2000u	/* 0.2s, unit is 0.1ms ,用于MCUA和B采样的不同步计算*/
#define	CH_EX_ASYNC_FILT_TWOHAND	10000u	/* 1.0s, unit is 0.1ms ,双手MA/MB采样不同步的计算*/
#define	CH_EX_ERR_FILT		50000u	/* 5s, unit is 0.1ms */
#define RST_LAG_TIME  3000u/* 0.3s, unit is 0.1ms,复位按钮延迟输出 */



void prg_init_val(void);

static void prg_di_filt(bool_t b8_curt_sta, di_filt_dat_t *stp_sta_dat, di_filt_dat_t *stp_sta_dat_bak);

					
void prg_run_logic(const uint8_t u8lc_init_val, const uint8_t u8lc_incr_val,const uint16_t *u16p_di_dat, uint16_t *u16p_do_dat);
static void prg_get_logic_in(uint16_t u16_mcua_di, uint16_t u16_mcub_di,uint8_t u8_dev_fault,instr_hmi_t *stp_sta_dat,instr_hmi_t *stp_sta_dat_bak);



static void prg_handle_control(uint16_t u16_idx); //处理功能块逻辑，并将结果赋值到对应功能块输出
bool_t prg_logic_AandB(bool_t b8_ch1, bool_t b8_ch2);  //A&B
bool_t prg_logic_AandBandC(bool_t b8_ch1, bool_t b8_ch2,bool_t b8_ch3); //A&B&C
bool_t prg_logic_AorB(bool_t b8_ch1, bool_t b8_ch2); //A||B
bool_t prg_logic_AorBorC(bool_t b8_ch1, bool_t b8_ch2,bool_t b8_ch3);//A||B||C
bool_t prg_logic_notA(bool_t b8_ch1);//!A
bool_t prg_handle_two_hand( bool_t b8_control_out, dev_input_res_t *stp_ch1,\
							 dev_input_res_t *stp_ch2,\
							dev_input_res_t *stp_ch1_bak,\
							dev_input_res_t *stp_ch2_bak); // two hand
bool_t prg_handle_rstltoh( bool_t b8_in, bool_t b8_control_out, dev_input_res_t *stp_rst, dev_input_res_t *stp_rst_bak);//复位上升沿
bool_t prg_handle_rsthtol( bool_t b8_in, bool_t b8_control_out, dev_input_res_t *stp_rst, dev_input_res_t *stp_rst_bak);//复位下降沿
bool_t prg_handle_rsthtoh( bool_t b8_in, bool_t b8_control_out, const dev_input_res_t *stp_rst, dev_input_res_t *stp_rst_bak);//复位高电平
bool_t prg_handle_delay_on ( bool_t b8_in, bool_t b8_control_out, uint32_t u32_tim_prm, layer_output_res_t *stp_delay, layer_output_res_t *stp_delay_bak);//延时闭合
bool_t prg_handle_delay_off( bool_t b8_in, bool_t b8_control_out, uint32_t u32_tim_prm, layer_output_res_t *stp_delay, layer_output_res_t *stp_delay_bak);//延时断开
bool_t prg_logic_AxnorB(bool_t b8_ch1, bool_t b8_ch2);//同或
bool_t prg_logic_AxorB(bool_t b8_ch1, bool_t b8_ch2); //异或

bool_t  prg_heart_beat_monitor(bool_t b8_in,  uint32_t u32_heart_tim, layer_output_res_t *hbs_delay, layer_output_res_t *hbs_delay_bak);  //心跳监控
bool_t  prg_fre_out(bool_t b8_in,  uint32_t u32_fre_tim, layer_output_res_t *fre_delay, layer_output_res_t *fre_delay_bak);  //频率输出

bool_t  prg_get_control_in(uint8_t address);
bool_t  prg_get_reset_in(uint8_t address);

void prg_copy_ram_BtoA(uint8_t *ram_a, uint8_t *ram_b, uint16_t u16_len);
void prg_red_flash(uint32_t u32_st_dev_sta_temp);
void prg_write_flash(void);
 void led_control(const uint8_t u8lc_init_val, const uint8_t u8lc_incr_val);
static void prg_handle_input(const uint16_t u16a_dat[], uint8_t u8_mcu_addr);
static void prg_relay_out_adj(bool_t b8_curt_val, uint8_t u8_mcu_addr,\
							uint8_t u8_ch_no, \
							relay_sta_dat_t *stp_ry_dat,\
							relay_sta_dat_t *stp_dat_bak);
					
#endif
